import { Controller, Post, Inject, Files, createMiddleware } from '@midwayjs/core';
import { UploadFileInfo, UploadMiddleware } from '@midwayjs/busboy';
import { MinioService } from '../utils/minio/minio';
import { DetectionService } from '../service/detection.service';
import { Context } from '@midwayjs/koa';


interface DetectionResult {
  image: string; // Base64编码的结果图
  ratio: number; // 堵塞比例
  diagnosis: string; // 诊断结果
}

@Controller('/api/ai-detection')
export class AIDetectionController {
  @Inject()
  minioService: MinioService;

  @Inject()
  detectionService: DetectionService;

  @Inject()
  ctx: Context;

  // Python Flask服务地址
  private readonly pythonServiceUrl = process.env.PYTHON_SERVICE_URL || 'http://127.0.0.1:8001';

  /**
   * 上传图片并进行腺样体检测
   */
  @Post('/detect', {
    middleware: [createMiddleware(UploadMiddleware, { mode: 'file' })]
  })
  async detect(@Files() files: UploadFileInfo[]) {
    try {
      // 1. 校验上传文件
      if (!files || !files.length) {
        return { code: 400, message: '未选择文件', data: null };
      }

      const file = files[0];

      // 2. 校验文件类型和大小
      const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
      if (!allowedTypes.includes(file.mimeType)) {
        return { code: 400, message: '仅支持 JPG、PNG 格式的图片', data: null };
      }

      const fs = require('fs');
      const computedSize = typeof (file as any).size === 'number'
        ? (file as any).size
        : (typeof (file as any).data === 'string'
            ? fs.statSync((file as any).data).size
            : (file as any).filepath
              ? fs.statSync((file as any).filepath).size
              : 0);
      if (computedSize === 0) {
        return { code: 400, message: '文件为空，请重新上传', data: null };
      }

      const maxSize = 5 * 1024 * 1024;
      if (computedSize > maxSize) {
        return { code: 400, message: '文件大小不能超过5MB', data: null };
      }

      // 3. 调用Python服务进行检测
      const detectionResult = await this.callPythonDetection(file);

      if (!detectionResult) {
        return { code: 500, message: '检测服务暂时不可用', data: null };
      }

      // 4. 上传原图到MinIO
      const originalImageUrl = await this.minioService.minioUpload([file]);

      // 5. 保存检测记录到数据库
      const userId = this.ctx.user?.userId;
      if (!userId) {
        return { code: 401, message: '用户未授权', data: null };
      }

      // 结果图存储到 MinIO，仅在库中保存 URL
      const { buffer: resultBuffer, ext: resultExt } = this.decodeBase64Image(detectionResult.image);
      const resultImageUrl = await this.minioService.uploadBuffer(resultBuffer, resultExt);

      const historyRecord = await this.detectionService.createHistoryWithDetails({
        userId,
        originalImageUrl,
        resultImage: resultImageUrl,
        ratio: detectionResult.ratio,
        diagnosis: detectionResult.diagnosis,
        filename: file.filename,
        fileSize: computedSize
      });

      return {
        code: 200,
        message: '检测完成',
        data: {
          id: historyRecord.id,
          originalImage: originalImageUrl,
          resultImageUrl,
          resultImage: resultImageUrl,
          ratio: detectionResult.ratio,
          diagnosis: detectionResult.diagnosis,
          createdAt: historyRecord.createdAt
        }
      };

    } catch (error) {
      console.error('Detection error:', error);
      return { code: 500, message: '检测失败: ' + error.message, data: null };
    }
  }

  /**
   * 调用Python Flask服务进行检测
   */
  private async callPythonDetection(file: UploadFileInfo): Promise<DetectionResult | null> {
    try {
      // 读取文件内容
      const fileBuffer = await this.getFileBuffer(file);

      // 创建FormData（优先使用原生 FormData/Blob；否则使用 form-data 包）
      const hasNativeForm = typeof (globalThis as any).FormData !== 'undefined' && typeof (globalThis as any).Blob !== 'undefined';
      const filename = file.filename || `image_${Date.now()}.${(file.mimeType || 'image/jpeg').split('/')[1] || 'jpg'}`;
      let form: any;
      let headers: any = undefined;
      let preferNodeFetch = false;
      if (hasNativeForm) {
        const NativeFormData = (globalThis as any).FormData;
        const NativeBlob = (globalThis as any).Blob;
        form = new NativeFormData();
        const blob = new NativeBlob([fileBuffer], { type: file.mimeType || 'application/octet-stream' });
        form.append('file', blob, filename);
      } else {
        const NodeFormData = require('form-data');
        form = new NodeFormData();
        form.append('file', fileBuffer, { filename, contentType: file.mimeType || 'application/octet-stream' });
        headers = { ...form.getHeaders() };
        preferNodeFetch = true;
      }

      // 调用Python服务
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(), 30000);

      const httpFetch = async (url: string, options: any) => {
        const gfetch = (globalThis as any).fetch;
        if (!preferNodeFetch && gfetch) return gfetch(url, options);
        const mod: any = await import('node-fetch');
        const df = mod.default ?? mod;
        return df(url, options);
      };

      try {
        const response = await httpFetch(`${this.pythonServiceUrl}/predict`, {
          method: 'POST',
          body: form,
          headers,
          signal: controller.signal
        });
        clearTimeout(timeout);

      if (!response.ok) {
          const errorText = await response.text();
          console.error('Python service error:', response.status, errorText);
          return null;
        }

        const result = await response.json();

        // 校验返回结果格式
        if (!result.image || typeof result.ratio !== 'number' || !result.diagnosis) {
          console.error('Invalid Python service response:', result);
          return null;
        }

        return {
          image: result.image,
          ratio: result.ratio,
          diagnosis: result.diagnosis
        };

      } catch (error) {
        clearTimeout(timeout);
        console.error('Error calling Python service:', error);
        return null;
      }
      // 外层 try 块收尾：如表单构造或文件读取异常
    } catch (error) {
      console.error('Error calling Python service (outer):', error);
      return null;
    }
  }

  /**
   * 获取文件buffer数据
   */
  private async getFileBuffer(file: UploadFileInfo): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      try {
        const fs = require('fs');
        if (file && (file as any).data && Buffer.isBuffer((file as any).data)) {
          resolve((file as any).data as Buffer);
          return;
        }
        const p = typeof (file as any).data === 'string' ? (file as any).data : (file as any).filepath;
        if (p) {
          fs.readFile(p, (err: any, data: Buffer) => {
            if (err) reject(err);
            else resolve(data);
          });
          return;
        }
        reject(new Error('无法读取文件数据'));
      } catch (e) {
        reject(e);
      }
    });
  }

  // 将 Base64（含或不含 dataURL 前缀）解码为 Buffer，并解析扩展名
  private decodeBase64Image(dataUrl: string): { buffer: Buffer; ext: string } {
    let ext = 'png';
    let base64 = dataUrl;
    const prefixMatch = /^data:image\/(\w+);base64,/i.exec(dataUrl);
    if (prefixMatch) {
      ext = prefixMatch[1] || ext;
      base64 = dataUrl.replace(/^data:image\/(\w+);base64,/i, '');
    }
    return { buffer: Buffer.from(base64, 'base64'), ext };
  }

  /**
   * 健康检查接口 - 检查Python服务状态
   */
  @Post('/health')
  async healthCheck() {
    try {
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(), 5000);

      const httpFetch = async (url: string, options: any) => {
        const gfetch = (globalThis as any).fetch;
        if (gfetch) return gfetch(url, options);
        const mod: any = await import('node-fetch');
        const df = mod.default ?? mod;
        return df(url, options);
      };

      try {
        const response = await httpFetch(`${this.pythonServiceUrl}/`, {
          method: 'GET',
          signal: controller.signal
        });
        clearTimeout(timeout);

        if (response.ok) {
          return {
            code: 200,
            message: '检测服务运行正常',
            data: { pythonService: 'online' }
          };
        } else {
          return {
            code: 503,
            message: '检测服务不可用',
            data: { pythonService: 'offline' }
          };
        }
      } catch (fetchError) {
        clearTimeout(timeout);
        throw fetchError;
      }
    } catch (error) {
      console.error('Health check error:', error);
      return {
        code: 503,
        message: '检测服务连接失败',
        data: { pythonService: 'offline' }
      };
    }
  }
}
